/**
 * Copyright &copy; 2012-2016 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
 */
package com.thinkgem.jeesite.modules.ins.service;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.thinkgem.jeesite.common.config.Global;
import com.thinkgem.jeesite.common.mapper.JsonMapper;
import com.thinkgem.jeesite.common.persistence.Page;
import com.thinkgem.jeesite.common.service.CrudService;
import com.thinkgem.jeesite.common.utils.CacheUtils;
import com.thinkgem.jeesite.common.utils.DocUtil;
import com.thinkgem.jeesite.common.utils.IdGen;
import com.thinkgem.jeesite.common.utils.StringUtils;
import com.thinkgem.jeesite.common.utils.WordToPDF;
import com.thinkgem.jeesite.modules.ins.dao.InsFieldDao;
import com.thinkgem.jeesite.modules.ins.dao.InsTableDao;
import com.thinkgem.jeesite.modules.ins.dao.InsTableUserDao;
import com.thinkgem.jeesite.modules.ins.entity.InsCategory;
import com.thinkgem.jeesite.modules.ins.entity.InsField;
import com.thinkgem.jeesite.modules.ins.entity.InsLog;
import com.thinkgem.jeesite.modules.ins.entity.InsTable;
import com.thinkgem.jeesite.modules.ins.entity.InsTableUser;
import com.thinkgem.jeesite.modules.ins.entity.InsTemplate;
import com.thinkgem.jeesite.modules.sys.entity.User;
import com.thinkgem.jeesite.modules.sys.utils.UserUtils;

/**
 * 检验报告书-数据表Service
 * @author fanqinglong
 * @version 2017-11-21
 */
@Service
@Transactional(readOnly = true)
public class InsTableService extends CrudService<InsTableDao, InsTable> {

	@Autowired
	private InsFieldDao insFieldDao;
	@Autowired
	private InsTableUserDao insTableUserDao;
	@Autowired
	private InsLogService insLogService;
	@Autowired
	private InsTemplateService insTemplateService;
	@Autowired
	private InsCategoryService insCategoryService;
	
	public InsTable get(String id) {
		InsTable insTable = super.get(id);
		insTable.setInsFieldList(insFieldDao.findList(new InsField(insTable)));
		return insTable;
	}
	
	public List<InsTable> findList(InsTable insTable) {
		return super.findList(insTable);
	}
	
	public Page<InsTable> findPage(Page<InsTable> page, InsTable insTable) {
		return super.findPage(page, insTable);
	}
	
	public String export(InsTable insTable,HttpServletRequest request){
		//获取数据
		Map<String, Object> dataMap = getDataMap(insTable);
		//导出word
		String url = DocUtil.createDoc(request, dataMap);
		if (url.indexOf("error:") <= -1 && "pdf".equals(Global.getConfig("printFormat"))) {
			String pdfUrl = "outPDF_"+System.currentTimeMillis()+".pdf";
			return WordToPDF.wordToPdf(request, url, pdfUrl);
		}
		return url;
	}
	
	private Map<String, Object> getDataMap(InsTable insTable){
		if (null == insTable) {
			return new HashMap<>();
		}
		Map<String, Object> dataMap = new HashMap<>();
		dataMap.put("name", insTable.getName());
		dataMap.put("fullname", insTable.getFullName());
		dataMap.put("category", null==insTable.getCategory()?"":insTable.getCategory().getName());
		dataMap.put("tableId", insTable.getTableId());
		dataMap.put("version", insTable.getVersion());
		dataMap.put("createBy", insTable.getCreateBy().getName());
		DateFormat df = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
		dataMap.put("createDate", df.format(insTable.getCreateDate()));
		List<InsField> fields = insTable.getInsFieldList();
		List<Map<String, String>> fieldMapList = new ArrayList<>(fields.size());
		for (int i = 0; i < fields.size(); i++) {
			InsField field = fields.get(i);
			Map<String, String> fieldMap = new HashMap<>();
			fieldMap.put("name", field.getName());
			fieldMap.put("code", field.getCode());
			switch (field.getType()) {
			case "1":
				fieldMap.put("type", "字符串");
				break;
			case "2":
				fieldMap.put("type", "数字");
				break;
			case "3":
				fieldMap.put("type", "年月日时分秒");
				break;
			case "4":
				fieldMap.put("type", "年月日");
				break;
			case "5":
				fieldMap.put("type", "年月");
				break;
			default:
				fieldMap.put("type", "字符串");
				break;
			}
			switch (field.getPreInput()) {
			case "0":
				fieldMap.put("preInput", "录入");
				break;
			case "1":
				fieldMap.put("preInput", "选择");
				break;
			case "2":
				fieldMap.put("preInput", "计算");
				break;

			default:
				fieldMap.put("preInput", "录入");
				break;
			}
			fieldMap.put("preValues", field.getPreValues());
			fieldMap.put("sort", field.getSort()+"");
			fieldMap.put("defaultValue", field.getDefaultValue());
			fieldMap.put("required", "1".equals(field.getRequired())?"是":"否");
			fieldMap.put("uniquely", "1".equals(field.getUniquely())?"是":"否");
			fieldMap.put("indexed", "1".equals(field.getIndexed())?"是":"否");
			fieldMapList.add(fieldMap);
		}
		dataMap.put("insFieldList", fieldMapList);
		return dataMap;
	}
	
	@Transactional(isolation = Isolation.DEFAULT,propagation = Propagation.REQUIRED,readOnly = false, rollbackFor = Exception.class)
	public void save(InsTable insTable) {
		Boolean flag = insTable.getIsNewRecord();
		InsTable oldTable = new InsTable();
		Map<String, InsTable> map = new HashMap<>();
		if (!flag) {
			oldTable = get(insTable.getId());
			map.put("oldTable", oldTable);
			map.put("insTable", insTable);
		}
		long diff = new Date().getTime() - Global.getBenchmarkDate().getTime();//计算到毫秒级别
		insTable.setTableId(IdGen.globalUniqueBase61(diff));
		super.save(insTable);
		// 如果是新添加的数据表，为创建者提供所有权限
		if (flag) {
			// 创建者自动成为该表的人员,并拥有所有操作的权限
			User currentUser = UserUtils.getUser();
			InsTableUser insTableUser = new InsTableUser();
			insTableUser.setTable(insTable);
			insTableUser.setUser(currentUser);
			insTableUser.setCode(255);
			insTableUser.preInsert();
			insTableUserDao.insert(insTableUser);
			//清除缓存
			CacheUtils.remove(UserUtils.USER_CACHE, UserUtils.USER_CACHE_ID_ + currentUser.getId());
			CacheUtils.remove(UserUtils.USER_CACHE, UserUtils.USER_CACHE_LOGIN_NAME_ + currentUser.getLoginName());
		}
		for (InsField insField : insTable.getInsFieldList()){
			if (insField.getId() == null){
				continue;
			}
			if (InsField.DEL_FLAG_NORMAL.equals(insField.getDelFlag())){
				insField.setPreValues(StringUtils.replaceHTMLentity(insField.getPreValues()));
				if (StringUtils.isBlank(insField.getId())){
					insField.setTable(insTable);
					insField.preInsert();
					insField.setFrequently("0");
					insFieldDao.insert(insField);
				}else{
					insField.preUpdate();
					insFieldDao.update(insField);
				}
			}else{
				insFieldDao.delete(insField);
			}
		}
		//日志添加
		if (null != insTable.getCategory().getId()) {
			InsCategory insCategory = insCategoryService.get(insTable.getCategory());
			insTable.setCategory(insCategory);
		}
		InsLog insLog = new InsLog(InsLog.MODULE_TABLE, flag?InsLog.TYPE_CREATE:InsLog.TYPE_SAVE, insTable, insTable.getId(), JsonMapper.toJsonString(flag?insTable:map));
		insLogService.save(insLog);
	}
	
	@Transactional(isolation = Isolation.DEFAULT,propagation = Propagation.REQUIRED,readOnly = false, rollbackFor = Exception.class)
	public String assignUser(InsTable insTable,String[] idsArr){
		StringBuilder msg = new StringBuilder();
		String names = "";
		int newNum = 0;
		for (int i = 0; i < idsArr.length; i++) {
			User user = UserUtils.get(idsArr[i]);
			if (null != user) {
				List<String> tableIdList = user.getTableIdList();
				//保证已有的人员不用重新授权
				if (tableIdList.contains(insTable.getId())) {
					continue;
				}
				//添加中间表信息
				InsTableUser insTableUser = new InsTableUser();
				insTableUser.preInsert();
				insTableUser.setUser(user);
				insTableUser.setTable(insTable);
				insTableUser.setCode(0);
				insTableUserDao.insert(insTableUser);
				//清除缓存
				CacheUtils.remove(UserUtils.USER_CACHE, UserUtils.USER_CACHE_ID_ + user.getId());
				CacheUtils.remove(UserUtils.USER_CACHE, UserUtils.USER_CACHE_LOGIN_NAME_ + user.getLoginName());
				msg.append("<br/>新增用户【" + user.getName() + "】到数据表【" + insTable.getName() + "】！");
				newNum++;
				names += ","+user.getName();
			}
		}
		if (newNum > 0) {
			InsLog insLog = new InsLog(InsLog.MODULE_TABLE, InsLog.TYPE_ASSIGN_USER, insTable, insTable.getId(), names.substring(1));
			insLogService.save(insLog);
		}
		return "已成功分配 "+newNum+" 个用户"+msg;
	}
	
	@Transactional(isolation = Isolation.DEFAULT,propagation = Propagation.REQUIRED,readOnly = false, rollbackFor = Exception.class)
	public void delete(InsTable insTable) {
		super.delete(insTable);
		/*insFieldDao.delete(new InsField(insTable));*/
		//日志添加
		if (null != insTable.getCategory().getId()) {
			InsCategory insCategory = insCategoryService.get(insTable.getCategory());
			insTable.setCategory(insCategory);
		}
		InsLog insLog = new InsLog(InsLog.MODULE_TABLE, InsLog.TYPE_DELETE, insTable, insTable.getId(), JsonMapper.toJsonString(insTable));
		insLogService.save(insLog);
	}
	
	@Transactional(isolation = Isolation.DEFAULT,propagation = Propagation.REQUIRED,readOnly = false, rollbackFor = Exception.class)
	public void bindTemplate(InsTable insTable){
		dao.bindTemplate(insTable);
		InsTemplate template = insTemplateService.get(insTable.getTemplate());
		//日志添加
		InsLog insLog = new InsLog(InsLog.MODULE_TABLE, InsLog.TYPE_BIND, insTable, insTable.getId(), template.getName());
		insLogService.save(insLog);
	}
	
	@Transactional(isolation = Isolation.DEFAULT,propagation = Propagation.REQUIRED,readOnly = false, rollbackFor = Exception.class)
	public void unBindTemplate(InsTable insTable){
		InsTable oldTable = dao.get(insTable.getId());
		dao.unBindTemplate(insTable);
		//日志添加
		InsLog insLog = new InsLog(InsLog.MODULE_TABLE, InsLog.TYPE_UNBIND, insTable, insTable.getId(), oldTable.getTemplate().getName());
		insLogService.save(insLog);
	}
	
	@Transactional(isolation = Isolation.DEFAULT,propagation = Propagation.REQUIRED,readOnly = false, rollbackFor = Exception.class)
	public void assignAuth(InsTable insTable){
		List<InsTableUser> tableUsers = insTable.getInsTableUserList();
		if (null != tableUsers && tableUsers.size() > 0) {
			//批量删除以前的这个数据表的授权
			insTableUserDao.deleteByTable(insTable.getId());
			//再新增
			for (InsTableUser insTableUser : tableUsers) {
				insTableUser.preInsert();
				insTableUser.setUser(UserUtils.get(insTableUser.getUser().getId()));
				insTableUserDao.insert(insTableUser);
			}
			insTable.setCreateName(insTable.getCreateBy().getName());
			//日志添加
			InsLog insLog = new InsLog(InsLog.MODULE_TABLE, InsLog.TYPE_ASSIGN_AUTH, insTable, insTable.getId(), JsonMapper.toJsonString(insTable));
			insLogService.save(insLog);
		}
	}
	
	public InsTable getByName(InsTable insTable){
		return dao.getByName(insTable);
	}
	
	/**
	 * 移除人员
	 * @param insTable
	 * @param user
	 * @return
	 */
	@Transactional(isolation = Isolation.DEFAULT,propagation = Propagation.REQUIRED,readOnly = false, rollbackFor = Exception.class)
	public Boolean outTable(InsTable insTable , User user){
		try {
			InsTableUser insTableUser = new InsTableUser();
			insTableUser.setTable(insTable);
			insTableUser.setUser(user);
			insTableUserDao.deleteByTableAndUser(insTableUser);
			//清除缓存
			CacheUtils.remove(UserUtils.USER_CACHE, UserUtils.USER_CACHE_ID_ + user.getId());
			CacheUtils.remove(UserUtils.USER_CACHE, UserUtils.USER_CACHE_LOGIN_NAME_ + user.getLoginName());
			//添加日志
			InsLog insLog = new InsLog(InsLog.MODULE_TABLE, InsLog.TYPE_OUT_TABLE, insTable, insTable.getId(), user.getName());
			insLogService.save(insLog);
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}
	
	/**
	 * 根据当前用户id和需要判断的授权码，拼出数据过滤SQL语句
	 * @param userId
	 * @param code
	 * @return
	 */
	public static String getDSF(String userId,String code){
		StringBuffer stringBuffer = new StringBuffer();
		stringBuffer.append("and a.id in (select t.id from ins_table t LEFT JOIN ins_table_user tu ON t.id = tu.table_id WHERE t.del_flag = '0' AND tu.user_id = '");
		stringBuffer.append(userId + "'");
		if (StringUtils.isNotBlank(code)) {
			stringBuffer.append(" AND tu.code & ");
			stringBuffer.append(code + "=" + code);
		}
		stringBuffer.append(")");
		return stringBuffer.toString();
	}
}